package code.lucamarrocco.struts2.rest;

import static code.lucamarrocco.rest.MethodsOrGoals.*;

import java.util.*;
import java.util.regex.*;

import javax.servlet.http.*;

import org.apache.struts2.dispatcher.mapper.*;

import code.lucamarrocco.rest.*;

import com.opensymphony.xwork2.config.*;
import com.opensymphony.xwork2.inject.*;

public class RestfulActionMapper extends DefaultActionMapper {
	private RestfulProtocolMather mather;

	public RestfulActionMapper() {}

	private RestfulProtocol restfulProtocol;

	public void setRestfulProtocol(RestfulProtocol restfulProtocol) {
		this.restfulProtocol = restfulProtocol;
	}

	@Inject(value = "restful.protocol")
	public void setRestfulProtocol(String restfulProcotolClassName) {

		try {
			restfulProtocol = (RestfulProtocol) getClass().getClassLoader().loadClass(restfulProcotolClassName).newInstance();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

		mather = new RestfulProtocolMather().using(restfulProtocol);
	}

	private boolean mustIgnoreThis(String uri) {
		if (uri.endsWith(".ico")) return true;
		if (uri.endsWith(".css")) return true;
		if (uri.endsWith(".js")) return true;
		if (uri.endsWith(".jpg")) return true;
		if (uri.endsWith(".gif")) return true;

		return false;
	}

	private String ignoreExtension(String uri) {
		for (String extension : extensions) {
			if (!extension.equals("") && uri.endsWith(extension)) return uri.replaceAll("\\." + extension + "$", "");
		}

		return uri;
	}

	private String withoutTransaction(String uri) {
		String T = null;
		if (!uri.matches("^.* /t/[^<>/]*/.*")) return uri;

			Matcher matcher = Pattern.compile("^.* /t/([^/]*).*").matcher(uri);
			if (matcher.matches()) {
				T = matcher.group(1);
				uri = uri.replaceAll("/t/[^/]*", "");
			}

		return uri;
	}

	@Override
	public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager configManager) {
		if (mustIgnoreThis(request.getRequestURI())) return super.getMapping(request, configManager);

		String uri = new Formatter().format("%s %s%s", request.getMethod(), request.getRequestURI(), methodOf(request.getQueryString())).toString();

		uri = withoutTransaction(uri);

		RestfulMethod method = mather.method(ignoreExtension(uri));

		if (method == null) return super.getMapping(request, configManager);

		return new RestfulActionMapping(uri, method);
	}
}